package com.dhecp.project.logstics.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONArray;
import com.dhecp.project.business.domain.*;
import com.dhecp.project.business.mapper.FbaPlanOrderDetailMapper;
import com.dhecp.project.logstics.domain.FbaBoxDetail;
import com.dhecp.project.logstics.mapper.*;
import com.dhecp.project.storage.domain.GaugeMaintenance;
import com.dhecp.project.storage.mapper.GaugeMaintenanceMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.RandomValueUtils;
import com.dhecp.core.constant.DataFiltering;
import com.dhecp.core.constant.ModuleTable;
import com.dhecp.core.utils.PageUtils;
import com.dhecp.framework.util.ShiroUtils;
import com.dhecp.project.common.domain.ModuleNidAndBid;
import com.dhecp.project.common.mapper.ModuleNidAndBidMapper;
import com.dhecp.project.common.service.impl.BaseModuleServiceImpl;
import com.dhecp.project.logstics.domain.FbaBox;
import com.dhecp.project.logstics.service.FbaShipmentService;
import com.dhecp.project.system.service.SysDictionaryForFieldService;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

/**
 * @Author fxz
 * @Description //头程货件业务层
 * @Date 2022/12/15 19:02
 **/
@Service
public class FbaShipmentServicelmpl extends BaseModuleServiceImpl implements FbaShipmentService {

    @Autowired
    private SysDictionaryForFieldService dictionaryForFieldService;

    @Autowired
    private FbaShipmentMapper fbaShipmentMapper;

    private String moduleTable = ModuleTable.FBA_BOX;

    @Autowired
    private ModuleNidAndBidMapper moduleNidAndBidMapper;

    @Autowired
    private FbaBoxMapper fbaBoxMapper;

    @Autowired
    private LogsticsMmodeCkMapper logsticsMmodeCkMapper;

    @Autowired
    private FbaBoxDetailMapper fbaBoxDetailMapper;

    @Autowired
    private GaugeMaintenanceMapper gaugeMaintenanceMapper;

    @Autowired
    private LogsticsMmodeMapper logsticsMmodeMapper;

    @Autowired
    private LogsticsMmodeGradsMapper logsticsMmodeGradsMapper;

    @Autowired
    private LogsticsMmodeDetailsMapper logsticsMmodeDetailsMapper;

    @Autowired
    private FbaPlanOrderDetailMapper fbaPlanOrderDetailMapper;


    /**
     * 查询头程计划单
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    public List<FbaShipment> queryList(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));	//常规查询条件SQL语句

        if (ShiroUtils.getUserDeptPath().equals("C101.D103")){
            params.put("datascode","(t1.effectStock = 1)");	//TODO 后期改对应销售部门对应的值
        } else {
            params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        }

        if (params.get("field") == null || params.get("field") == ""){
            String orderBy = "t1.createTime DESC";
            PageUtils.startPageOrder(orderBy);
        }else{
            PageUtils.startPage();
        }

        return fbaShipmentMapper.select(params);
    }

    /**
     * 修改审核状态
     * @return
     * @author DH-Xxj
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult updateState(Map<String, Object> params) {
        List<FbaShipment> fbaShipmentList =  JSON.parseArray(params.get("infoItems").toString(), FbaShipment.class);
        FbaShipment fbaShipment1;
        for (FbaShipment fbaShipment:fbaShipmentList
        ) {
            fbaShipment1 = fbaShipmentMapper.queryFirstByGuid(fbaShipment.getGuid());
            if (fbaShipment1.getState().equals("1")){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("该头程货件单已审核,核实后再操作!");
            }
            fbaShipment.setUpdateTime(new Date());
            fbaShipment.setState(params.get("state").toString());
            fbaShipment.setAuditTime(new Date());
            fbaShipment.setAuditUser(ShiroUtils.getUserId());
            fbaShipmentMapper.update(fbaShipment);

            //查询物流方式仓库梯度信息
            Map<String, Object> params11 = new HashMap<String, Object>();
            params11.put("logisticsMmodeGuid",fbaShipment.getLogisticsMmodeGuid());
            List<LogisticsMmodeCk> logisticsMmodeCkList = logsticsMmodeCkMapper.findLogisticsMmodeCk(params11);
            List<LogisticsMmodeCk> logisticsMmodeCkS = new ArrayList<>();
            if (logisticsMmodeCkList.size() != 0){
                logisticsMmodeCkS  = logisticsMmodeCkList.stream().filter(logisticsMmodeCk ->
                        fbaShipment.getDestinationFulfillmentCenterId().equals(logisticsMmodeCk.getWarehouseName())).collect(Collectors.toList());
            }

            //查询装箱最新数据
            Map<String, Object> params1 = new HashMap<String, Object>();
            params1.put("moduleTable", moduleTable);
            ModuleNidAndBid moduleNidAndBid = moduleNidAndBidMapper.findModuleNidAndBid(params1);    //有事务控制，制单异常不跳过单号
            //新增头程装箱单
            FbaBox fbaBox = new FbaBox();
            fbaBox.setGuid(RandomValueUtils.getGUID());
            fbaBox.setNid(moduleNidAndBid.getNid());
            fbaBox.setBid(moduleNidAndBid.getBid());
            fbaBox.setCid(ShiroUtils.getMandatorCid());
            fbaBox.setCidName(ShiroUtils.getMandatorCidName());
            fbaBox.setbUser(ShiroUtils.getMandatorId());
            fbaBox.setbUserName(ShiroUtils.getMandatorName());
            fbaBox.setbDept(ShiroUtils.getMandatorDeptPath());
            fbaBox.setbDeptName(ShiroUtils.getMandatorDeptName());
            fbaBox.setbPosition(ShiroUtils.getMandatorPositionNameDa());
            fbaBox.setaUser(ShiroUtils.getUserId());
            fbaBox.setaUserName(ShiroUtils.getUserName());
            fbaBox.setaDept(ShiroUtils.getUserDeptPath());
            fbaBox.setaDeptName(ShiroUtils.getUserDeptName());
            fbaBox.setaPosition(ShiroUtils.getUserPositionNameDa());
            fbaBox.setCode(moduleNidAndBid.getBid());
            fbaBox.setState("0");
            fbaBox.setStateName("未装箱");
            fbaBox.setStatePrint("0");
            fbaBox.setStatePrintName("配货清单未打印");
            fbaBox.setStateTrack("0");
            fbaBox.setStateTrackName("无");
            fbaBox.setCodeShipment(fbaShipment.getCode());
            fbaBox.setCreateTime(new Date());
            fbaBox.setCreateUser(ShiroUtils.getUserId());
            fbaBox.setNumBox(0);
            fbaBox.setWeightReal(new BigDecimal(0));
            fbaBox.setWeightVol(new BigDecimal(0));
            fbaBox.setWeightCal(fbaShipment.getWeightCalPredict());
            fbaBox.setDestinationFulfillmentCenterId(fbaShipment.getDestinationFulfillmentCenterId());
            fbaBox.setShipmentId(fbaShipment.getShipmentId());
            fbaBox.setvZdbz(fbaShipment.getvZdbz());
            fbaBox.setPriceTranPredict(fbaShipment.getPriceTranPredict());
            fbaBox.setPriceCalPerKg(fbaShipment.getPriceCalPerKg());
            fbaBox.setPriceTranCalWeightPredict(fbaShipment.getPriceTranCalWeightPredict());
            fbaBox.setPriceQualityExtra(fbaShipment.getPriceQualityExtra());
            fbaBox.setPriceQualityExtraPerKg(fbaShipment.getPriceQualityExtraPerKg());
            fbaBox.setPriceQualityExtraPredict(fbaShipment.getPriceQualityExtraPredict());
            fbaBox.setNumProName(fbaShipment.getNumProName());
            fbaBox.setNumProNameBeyond(fbaShipment.getNumProNameBeyond());
            fbaBox.setPriceProNamePerOne(fbaShipment.getPriceProNamePerOne());
            fbaBox.setPriceProNameExtraPredict(fbaShipment.getPriceProNameExtraPredict());
            fbaBox.setZysx(fbaShipment.getZysx());
            fbaBox.setCodeCompany(fbaShipment.getCodeCompany());
            fbaBox.setNameCompany(fbaShipment.getNameCompany());
            fbaBox.setCodeLogsticsPattern(fbaShipment.getCodeLogsticsPattern());
            fbaBox.setNameLogsticsPattern(fbaShipment.getNameLogsticsPattern());
            fbaBox.setNameLogsticsWay(fbaShipment.getNameLogsticsWay());
            fbaBox.setNameLogsticsClearance(fbaShipment.getNameLogsticsClearance());
            fbaBox.setStateShareTicket(String.valueOf(fbaShipment.getStateShareTicket()));
            fbaBox.setStateShareTicketName(fbaShipment.getStateShareTicket() == 0 ?"否":"是");
            fbaBox.setPriceClearanceOpe(fbaShipment.getPriceClearanceOpe());
            fbaBox.setCoefficientWeight(new BigDecimal(fbaShipment.getCoefficientWeight()));
            fbaBox.setToPurchasePrice(String.valueOf(fbaShipment.getToPurchasePrice()));
            fbaBox.setRealityPurchasePrice("0");
            fbaBox.setPriceSingleBoxReq(fbaShipment.getPriceSingleBoxReq());
            fbaBox.setIsBinning("否");
            fbaBox.setvGsJc(fbaShipment.getvGsJc());
            fbaBox.setSinglePassCrane(fbaShipment.getSinglePassCrane());
            fbaBox.setWeightCalBySingle(fbaShipment.getWeightCalBySingle());
            fbaBox.setJzPrice(fbaShipment.getJzPrice());
            fbaBox.setPzjzPrice(fbaShipment.getPzjzPrice());
            fbaBox.setLogisticsType(fbaShipment.getLogisticsType());
            fbaBox.setTdjzPrice(fbaShipment.getTdjzPrice());
            fbaBox.setJettisonCoe(fbaShipment.getJettisonCoe());
            fbaBox.setSurchargeMaterialMax(fbaShipment.getSurchargeMaterialMax());
            fbaBox.setNameSurchargePrice(fbaShipment.getNameSurchargePrice());
            fbaBox.setPriceClearanceOpePrice(fbaShipment.getPriceClearanceOpePrice());
            fbaBox.setTradeNamePro(fbaShipment.getTradeNamePro());
            fbaBox.setPriceClearanceOpeCs(fbaShipment.getPriceClearanceOpeCs());
            fbaBox.setNumMaxProName(fbaShipment.getNumMaxProName());
            fbaBox.setNumFreeProName(fbaShipment.getNumFreeProName().toString());
            fbaBox.setJettisonWeightCharge(fbaShipment.getJettisonWeightCharge());
            fbaBox.setActualLogisticsFreight(fbaShipment.getPriceTranPredict());
            fbaBox.setLogisticsMmodeGuid(fbaShipment.getLogisticsMmodeGuid());
            fbaBox.setNumFreeProNameNew(fbaShipment.getNumFreeProNameNew());
            fbaBox.setIsTracking("否");
            fbaBox.setWeightCalA1(BigDecimal.ZERO);
            fbaBox.settCNum(0);
            if (logisticsMmodeCkS.size() != 0){
                fbaBox.setWarehouseSurchargePrice(logisticsMmodeCkS.get(0).getWarehouseCost());
            }else {
                fbaBox.setWarehouseSurchargePrice(BigDecimal.ZERO);
            }
            fbaBox.setWarehouseSurcharge(BigDecimal.ZERO);
            //抛重发货数据
            fbaBox.setLoadDelivery("否");
            fbaBox.setActualLogisticsFreightPf(BigDecimal.ZERO);
            fbaBox.setPriceTranCalWeightPredictPf(BigDecimal.ZERO);
            fbaBox.setPriceQualityExtraPredictPf(BigDecimal.ZERO);
            fbaBox.setPriceProNameExtraPredictPf(BigDecimal.ZERO);
            fbaBox.setPriceClearanceOpePf(BigDecimal.ZERO);
            fbaBox.setNumFreeProNamePf(fbaShipment.getNumFreeProName());
            fbaBox.setPriceSingleBoxReqZd(fbaShipment.getPriceSingleBoxReqZd());
            fbaBox.setCurrencyAmount(fbaShipment.getCurrencyAmount());
            fbaBox.setCurrency(fbaShipment.getCurrency());
            fbaBoxMapper.insertFbaBox(fbaBox);

            if (fbaShipment.getIsDeliver() == 1){
                //直接进入变成头程装箱，已装箱状态，箱规参照系统默认或头程计划单选择的箱规标准
                AjaxResult generate = generate(fbaBox, params, fbaShipment);
                if (generate.get("code").equals(500)){
                    return generate;
                }
            }
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public FbaShipment queryFirstRecord(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        return fbaShipmentMapper.selectFirstRecordByNid(params);
    }

    @Override
    public FbaShipment queryByCode(String code) throws Exception {
        return fbaShipmentMapper.findFbaShipmentByCode(code);
    }

    /**
     * 自动生成装箱数据
     */
    private AjaxResult generate(FbaBox fbaBox1,Map<String, Object> params,FbaShipment fbaShipment) {
        //箱规维护
        List<GaugeMaintenance> gaugeMaintenanceList = gaugeMaintenanceMapper.select();
        //根据头程货件单号查询货件详情信息
        params.put("codeShipment",fbaBox1.getCodeShipment());
        List<FbaBoxDetail> queryList = fbaBoxDetailMapper.select(params);

        //每个商品的箱子数据
        List<FbaBoxDetail> fbaBoxDetailListNew = new ArrayList<>();
        FbaBoxDetail fbaBoxDetailNew;
        List<FbaBoxDetail> fbaBoxDetailList;

        Map<String, Object> params11 = new HashMap<String, Object>();
        params11.put("guid",fbaBox1.getLogisticsMmodeGuid());
        //查询物流方式
        LogisticsMmode logisticsMmode = logsticsMmodeMapper.queryFirstByGuid(params11);
        //获取物流方式详情
        Map<String, Object> params4 = new HashMap<String, Object>();
        params4.put("logisticsMmodeGuid",fbaBox1.getLogisticsMmodeGuid());
        List<LogisticsMmodeDetails> textureList = logsticsMmodeDetailsMapper.findLogisticsMmodeDetails(params4);
        //获取物流方式梯度
        List<LogisticsMmodeGrads> logisticsMmodeGradList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);
        List<LogisticsMmodeGrads> logisticsMmodeGrads  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFS".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeGrads> logisticsMmodeInfoItems  = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 ->
                "WLFSTDJZ".equals(logisticsMmodeGrads1.getType())).collect(Collectors.toList());
        List<LogisticsMmodeCk> logisticsMmodeCkList = logsticsMmodeCkMapper.findLogisticsMmodeCk(params4);

        params4.remove("logisticsMmodeGuid");
        params4.put("type","WLPMTD");
        //获取品名梯度详情
        List<LogisticsMmodeGrads> wlpmtdList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params4);

        //单箱采购总价
        BigDecimal priceSingleBoxReqTol;

        FbaBoxDetail fbaBoxDetail;

        //查询头程计划详情信息
        Map<String, Object>  params1 = new HashMap<String, Object>();
        params1.put("code", fbaShipment.getCodePlan());
        List<FbaPlanOrderDetail> fbaPlanOrderDetailList = fbaPlanOrderDetailMapper.queryList(params1);
        for (FbaPlanOrderDetail fbaPlanOrderDetail : fbaPlanOrderDetailList) {
            //根据头程箱数新增
            for (int j = 0; j < fbaPlanOrderDetail.getNumPlanDeliver() / fbaPlanOrderDetail.getGaugeMaintenanceNum(); j++) {
                fbaBoxDetailNew = new FbaBoxDetail();
                fbaBoxDetailNew.setGuid(RandomValueUtils.getGUID());
                //关联头程计划详情
                fbaBoxDetailNew.setCodeBox(fbaBox1.getCode());
                fbaBoxDetailNew.setCodeShipment(fbaBox1.getCodeShipment());
                fbaBoxDetailNew.setBoxIndex(j);
                fbaBoxDetailNew.setBUser(ShiroUtils.getMandatorId());
                fbaBoxDetailNew.setBDept(ShiroUtils.getMandatorDeptPath());
                fbaBoxDetailNew.setDeleted(0);
                fbaBoxDetailNew.setCreateTime(new Date());
                fbaBoxDetailNew.setCreateUser(ShiroUtils.getMandatorId());

                priceSingleBoxReqTol = BigDecimal.ZERO;
                fbaBoxDetailList = new ArrayList<>();
                //匹配箱规维护
                List<GaugeMaintenance> gaugeMaintenanceListNew = gaugeMaintenanceList.stream().filter(
                        gaugeMaintenance -> gaugeMaintenance.getId().equals(fbaPlanOrderDetail.getGaugeMaintenanceId())
                ).collect(Collectors.toList());
                if (gaugeMaintenanceListNew.size() == 0){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error(fbaPlanOrderDetail.getCommodityCode()+"该箱规未维护,审核失败!");
                }
                //将每箱子的数据赋值到NumRealityDeliver字段上
                for (int i = 0; i < queryList.size(); i++) {
                    fbaBoxDetail = new FbaBoxDetail();
                    BeanUtils.copyProperties(queryList.get(i),fbaBoxDetail);
                    fbaBoxDetail.setNumPlanDeliver(String.valueOf(queryList.get(i).getNumPlanDeliver()));
                    if (queryList.get(i).getGuidKc().equals(fbaPlanOrderDetail.getGuidKc())){
                        fbaBoxDetail.setNumRealityDeliver(String.valueOf(fbaPlanOrderDetail.getGaugeMaintenanceNum()));
                        //计算单箱采购单价
                        priceSingleBoxReqTol = priceSingleBoxReqTol.add(new BigDecimal(fbaPlanOrderDetail.getGaugeMaintenanceNum()).multiply(new BigDecimal(queryList.get(i).getPriceIn())));
                    }
                    fbaBoxDetail.setSerial(String.valueOf(i));
                    fbaBoxDetailList.add(fbaBoxDetail);
                }

                fbaBoxDetailNew.setWeight(String.valueOf(gaugeMaintenanceListNew.get(0).getWeight()));
                fbaBoxDetailNew.setLength(String.valueOf(gaugeMaintenanceListNew.get(0).getLength()));
                fbaBoxDetailNew.setWidth(String.valueOf(gaugeMaintenanceListNew.get(0).getWidth()));
                fbaBoxDetailNew.setHeight(String.valueOf(gaugeMaintenanceListNew.get(0).getHeight()));
                //计算抛重
                BigDecimal weighVol =
                        (new BigDecimal(fbaBoxDetailNew.getLength()).multiply(new BigDecimal(fbaBoxDetailNew.getWidth()))
                                .multiply(new BigDecimal(fbaBoxDetailNew.getHeight())))
                                .divide(new BigDecimal(logisticsMmode.getCoefficientWeight()),2, RoundingMode.HALF_UP);
                fbaBoxDetailNew.setWeightVol(String.valueOf(weighVol));
                fbaBoxDetailNew.setPriceSingleBoxReq(priceSingleBoxReqTol);
                //将其他箱数的值统一赋值一个值上
                fbaBoxDetailNew.setProductInfo(JSONArray.toJSONString(fbaBoxDetailList));
                fbaBoxDetailListNew.add(fbaBoxDetailNew);
            }
        }

        List<FbaBoxDetail> fbaBoxDetailListInset = new ArrayList<>();
        //历史的商品信息
        List<FbaBoxDetail> fbaBoxDetailListOld;
        BigDecimal weightReal;
        BigDecimal weightVol;
        BigDecimal predVal;
        BigDecimal weightCal;
        BigDecimal weightCalNew;
        BigDecimal max_result;
        BigDecimal texture;
        BigDecimal weightPrice;
        BigDecimal phweightPrice;
        BigDecimal priceClearanceOpePrice;
        BigDecimal tradeNamePro;
        Boolean numWeightCal;
        Integer numProName;
        Integer num;
        Double numFreeProName;
        BigDecimal priceTranCalWeightPredict;
        BigDecimal warehouseSurcharge;
        BigDecimal weightVolPredictNew;
        String surchargeMaterialMax;
        BigDecimal weightCalBySingle;
        List<LogisticsMmodeGrads> tdjzPrice;
        List<LogisticsMmodeGrads> pzjzPrice;
        List<LogisticsMmodeGrads> phjzPrice;
        List<LogisticsMmodeGrads> qgPrice;
        Set<String> gradeNum;
        //总箱重
        weightReal = BigDecimal.ZERO;
        //总抛重
        weightVol = BigDecimal.ZERO;
        //最大的材质值
        texture = BigDecimal.ZERO;
        //最大值材质名称
        surchargeMaterialMax = "";
        //实际计重之和
        weightCal = BigDecimal.ZERO;
        //最大值
        max_result = BigDecimal.ZERO;
        //实际计重约分
        weightCalNew = BigDecimal.ZERO;
        //抛货系数
        predVal = BigDecimal.ZERO;
        //计重单价
        weightPrice = BigDecimal.ZERO;
        //抛重梯度计重单价
        weightVolPredictNew = BigDecimal.ZERO;
        //抛重计重单价
        phweightPrice = BigDecimal.ZERO;
        //实际计重费
        priceTranCalWeightPredict = BigDecimal.ZERO;
        //仓库附加计重费用
        warehouseSurcharge = BigDecimal.ZERO;
        //品名数除上限数
        tradeNamePro = BigDecimal.ZERO;
        //清关费
        priceClearanceOpePrice = BigDecimal.ZERO;
        //品名判断数值
        numWeightCal = true;
        //实际品名数
        numProName = 0;
        //超出品名
        num = 0;
        //实际品名免费数
        numFreeProName = 0.0;
        //品名数量
        gradeNum = new HashSet<>();
        for (int boxIndex = 0; boxIndex < fbaBoxDetailListNew.size(); boxIndex++) {
            //实际的商品信息
            fbaBoxDetailListOld = JSON.parseArray(fbaBoxDetailListNew.get(boxIndex).getProductInfo(), FbaBoxDetail.class);

            //计算抛重和实重的数据和采购价
            weightReal = weightReal.add(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
            weightVol = weightVol.add(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
            //MAX（单箱抛重，单箱起重）
            weightVolPredictNew = weightVolPredictNew.add(logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol())));

            //物流方式==是
            if (fbaBox1.getStateShareTicketName().equals("是")) {
                if (fbaBox1.getLogisticsType().equals("快递")) {
                    //实际计重=MAX（实重,抛重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(precision(max_result));
                    //实际计重=MAX（A1，单票起重）
                    weightCal = logisticsMmode.getSinglePassCrane().max(weightCal);
                }else {
                    //实际计重=MAX（实重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    //实际计重之和
                    weightCal = weightCal.add(max_result);
                }
            } else {
                if (fbaBox1.getLogisticsType().equals("快递")) {
                    //实际计重=MAX（实重,抛重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(precision(max_result));
                    fbaBox1.setWeightCalA1(weightCal);
                    //实际计重=MAX（A1，单票起重）
                    weightCal = logisticsMmode.getSinglePassCrane().max(weightCal);
                }else {
                    //实际计重=MAX（实重,抛重,单箱起重）
                    max_result = logisticsMmode.getWeightCalBySingle().max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeight()));
                    max_result = max_result.max(new BigDecimal(fbaBoxDetailListNew.get(boxIndex).getWeightVol()));
                    //实际计重之和
                    weightCal = weightCal.add(max_result);
                }
            }

            //重新计算是第几箱子
            fbaBoxDetailListNew.get(boxIndex).setBoxIndex(boxIndex);

            for (FbaBoxDetail  fbaBoxDetail1 : fbaBoxDetailListOld){
                //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断品名数
                //不一样的品名数=(商品中文、海关编码、材质中文只要一个不同)
                String join = fbaBoxDetail1.getNameGoodsCn() + '-' + fbaBoxDetail1.getCodeGoodsHs() + '-' +fbaBoxDetail1.getNameMaterialCn();
                gradeNum.add(join);

                //判断是否是混合材质
                //TODO 判断十个箱子里面的值是否有值 再来判断是否需要判断材质值
                if (fbaBoxDetail1.getNameMaterialCn().indexOf(",") == -1) {
                    //赋值材质附加费(取最大值)
                    for (int j = 0; j < textureList.size(); j++) {
                        if (textureList.get(j).getMaterialName().equals(fbaBoxDetail1.getNameMaterialCn())) {
                            if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                texture = (textureList.get(j).getMaterialCost());
                                surchargeMaterialMax = (textureList.get(j).getMaterialName());
                            }
                        }
                    }
                } else {
                    String[] nameMaterialCnList = fbaBoxDetail1.getNameMaterialCn().split(",");
                    for (String nameMaterialCn : nameMaterialCnList){
                        for (int j = 0; j < textureList.size(); j++) {
                            if (textureList.get(j).getMaterialName().equals(nameMaterialCn)) {
                                if (textureList.get(j).getMaterialCost().compareTo(texture) > 0) {
                                    texture = (textureList.get(j).getMaterialCost());
                                    surchargeMaterialMax = (textureList.get(j).getMaterialName());
                                }
                            }
                        }
                    }
                }
            }
        }

        //约分
        weightVolPredictNew = precision(weightVolPredictNew);

        //是否拼票是
        if (fbaBox1.getStateShareTicketName().equals("是")) {
            //计重约分
            if (fbaBox1.getLogisticsType().equals("快递")) {
                weightCalNew = weightCal;
            }else {
                weightCalNew = precision(weightCal);
            }
            //梯度计重单价=(实际计重满足区间的值)
            BigDecimal finalWeightCalNew = weightCalNew;
            tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //抛货系数=(抛重的值-计重的值)
            predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //抛货计重单价=(抛货系数满足区间的值)
            BigDecimal finalPredVal = predVal;
            pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //计重单价=梯度计重单价+抛重计重单价
            weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO).add(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);

            phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

            //抛重>实重，实际计重费=MIN(实际计重*计重单价,抛货计重费)；抛重<实重，实际计重费=实际计重*计重单价；
            priceTranCalWeightPredict = (weightCalNew.multiply(weightPrice)).setScale(2, BigDecimal.ROUND_HALF_UP);
            if (weightVol.compareTo(weightReal) > 0){
                if (priceTranCalWeightPredict.compareTo(weightVolPredictNew.multiply(phweightPrice))>=0){
                    fbaBox1.setPriceTranCalWeightPredict(weightVolPredictNew.multiply(phweightPrice));
                }else {
                    fbaBox1.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
                }
            }else {
                fbaBox1.setPriceTranCalWeightPredict(priceTranCalWeightPredict);
            }
            //1.实际计重<单票起重的二分之一,实际品名数=免费品名数/2&向下取整
            numWeightCal = weightCalNew.compareTo(fbaBox1.getSinglePassCrane().divide(new BigDecimal(2)))<0;
            //实际品名数
            numProName = gradeNum.size();
            if (numWeightCal){
                numFreeProName = Math.floor(fbaBox1.getNumFreeProNameNew()/2.0);
            }
            //2.实际计重>=单票起重的二分之一,实际品名数=免费品名数/2&向上取整
            if (!numWeightCal && weightCalNew.compareTo(fbaBox1.getSinglePassCrane())<0){
                numFreeProName = Math.ceil(fbaBox1.getNumFreeProNameNew()/2.0);
            }
            if (weightCalNew.compareTo(fbaBox1.getSinglePassCrane()) >= 0){
                //3.实际计重>=单票起重,实际品名数=免费品名数
                numFreeProName = fbaBox1.getNumFreeProNameNew().doubleValue();
            }
            //超出品名=实际品名-实际免费品名数
            num = numProName-numFreeProName.intValue();
            //品名免费数
            fbaBox1.setNumFreeProName(String.valueOf(numFreeProName.intValue()));
            fbaBox1.setNumProName(numProName);
            //清关费=清关费*清关占比
            if (fbaBox1.getNumMaxProName()!= 0){
                //品名数/上限数
                tradeNamePro = new BigDecimal(gradeNum.size()).divide(new BigDecimal(logisticsMmode.getNumMaxProName()),2,RoundingMode.HALF_UP);
                BigDecimal finalTradeNamePro = tradeNamePro;
                qgPrice = wlpmtdList.stream().filter(logisticsMmodeGrads1 -> finalTradeNamePro.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                        && finalTradeNamePro.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
                priceClearanceOpePrice = qgPrice.size()!=0?qgPrice.get(0).getKg():BigDecimal.ZERO;
            }
            //预估清光费(物流方式清光费*品名占比)
            fbaBox1.setPriceClearanceOpe((logisticsMmode.getPriceClearanceOpe().multiply(priceClearanceOpePrice)).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));
            //清光费单价
            fbaBox1.setPriceClearanceOpePrice(logisticsMmode.getPriceClearanceOpe());
        } else {
            //计重约分
            if (fbaBox1.getLogisticsType().equals("快递")) {
                weightCalNew = weightCal;
            }else {
                weightCalNew = new BigDecimal(Math.ceil(weightCal.doubleValue()));
                fbaBox1.setWeightCalA1(weightCalNew);
                //实际计重=MAX（A1，单票起重）
                weightCalNew = logisticsMmode.getSinglePassCrane().max(weightCalNew);
            }
            //梯度计重单价=(实际计重满足区间的值)
            BigDecimal finalWeightCalNew = weightCalNew;
            tdjzPrice = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> finalWeightCalNew.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalWeightCalNew.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //抛货系数=(抛重的值-计重的值)
            predVal = (weightVol.subtract(weightCalNew)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //抛货计重单价=(抛货系数满足区间的值)
            BigDecimal finalPredVal = predVal;
            pzjzPrice = logisticsMmodeInfoItems.stream().filter(logisticsMmodeGrads1 -> finalPredVal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalPredVal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //计重单价=梯度计重单价+抛重计重单价
            weightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);
            phweightPrice = (tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);

            //实际计重费=(预估计重*计重单价)
            fbaBox1.setPriceTranCalWeightPredict((weightCalNew.multiply(weightPrice)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //超出品名=实际品名-实际免费品名数
            num = gradeNum.size()-numFreeProName.intValue();
            //实际清光费
            fbaBox1.setPriceClearanceOpe(logisticsMmode.getPriceClearanceOpe());
            fbaBox1.setNumProName(gradeNum.size());
        }

        List<LogisticsMmodeCk> logisticsMmodeCkS = new ArrayList<>();
        if (logisticsMmodeCkList.size() != 0){
            logisticsMmodeCkS  = logisticsMmodeCkList.stream().filter(logisticsMmodeCk ->
                    fbaBox1.getDestinationFulfillmentCenterId().equals(logisticsMmodeCk.getWarehouseName())).collect(Collectors.toList());
        }

        if (logisticsMmodeCkS.size() != 0){
            fbaBox1.setWarehouseSurchargePrice(logisticsMmodeCkS.get(0).getWarehouseCost());
        }else {
            fbaBox1.setWarehouseSurchargePrice(BigDecimal.ZERO);
        }
        //仓库附加计重费用 = 仓库附件计重单价*实际计重
        warehouseSurcharge = (weightCalNew.multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
        fbaBox1.setWarehouseSurcharge(warehouseSurcharge);
        fbaBox1.setPriceTranCalWeightPredict(fbaBox1.getPriceTranCalWeightPredict().add(warehouseSurcharge));

        //实际实重
        fbaBox1.setWeightReal(weightReal);
        //实际抛重
        fbaBox1.setWeightVol(weightVol);
        //装箱计重
        fbaBox1.setWeightCal(weightCalNew);
        //头程箱数
        fbaBox1.setNumBox(fbaBoxDetailListNew.size());
        //抛货系数
        fbaBox1.setJettisonCoe(predVal);
        //梯度计重单价
        fbaBox1.setTdjzPrice(tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO);
        //抛货计重单价
        fbaBox1.setPzjzPrice(pzjzPrice.size()!=0?pzjzPrice.get(0).getKg():BigDecimal.ZERO);
        //计重单价
        fbaBox1.setJzPrice(weightPrice);
        //抛货计重费
        fbaBox1.setJettisonWeightCharge(weightVolPredictNew.multiply(phweightPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
        //设置表头附加费材质
        fbaBox1.setPriceQualityExtra(texture);
        //最大附加费材质
        fbaBox1.setSurchargeMaterialMax(surchargeMaterialMax);
        //设置实际材质附加费=材质计费*实际计重
        fbaBox1.setPriceQualityExtraPredict(texture.multiply(weightCalNew).setScale(2, BigDecimal.ROUND_HALF_UP));
        //品名
        fbaBox1.setNumProNameBeyond(num>0?num:0);
        //占比
        fbaBox1.setTradeNamePro(priceClearanceOpePrice);
        //实际品名附加费 = 超出的品名*品名标准
        fbaBox1.setPriceProNameExtraPredict(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(fbaBox1.getNumProNameBeyond())).setScale(2, BigDecimal.ROUND_HALF_UP));
        //实际物流费用 = 实际计重运费+实际材质附加费+实际品名附加费+实际清关费
        fbaBox1.setActualLogisticsFreight(fbaBox1.getPriceTranCalWeightPredict().
                add(fbaBox1.getPriceQualityExtraPredict()).add(fbaBox1.getPriceProNameExtraPredict()
                .add(fbaBox1.getPriceClearanceOpe())));

        //判断是否是抛重发货 -- 进行逻辑计算
        if (fbaBox1.getLoadDelivery().equals("是")){
            //实际抛发清关费=清关费单价
            fbaBox1.setPriceClearanceOpePf(logisticsMmode.getPriceClearanceOpe());
            //抛发实际品名免费数=品名免费数
            fbaBox1.setNumFreeProNamePf(logisticsMmode.getNumFreeProName());
            //抛发超品名数量【=实际品名数-抛发实际品名免费数】
            int numPf = fbaBox1.getNumProName() - fbaBox1.getNumFreeProNamePf();
            numPf = numPf>0?numPf:0;
            //实际抛发品名附加费、费用说明：实际抛发品名附加费=超品名数量*品名附加费单价
            fbaBox1.setPriceProNameExtraPredictPf(logisticsMmode.getPriceProNamePerOne().multiply(new BigDecimal(numPf)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //抛发计重：【=MAX（装箱抛重，单票起重）约分】
            BigDecimal weightCalPf = precision(logisticsMmode.getSinglePassCrane().max(weightVol));
            //实际抛发材质附加费、费用说明：实际抛发材质附加费=MAX（装箱抛重，单票起重）*材质附加单价
            fbaBox1.setPriceQualityExtraPredictPf(weightCalPf.multiply(fbaBox1.getPriceQualityExtra()).setScale(2, BigDecimal.ROUND_HALF_UP));
            //抛发计重单价：【抛发计重对应的梯度价】
            List<LogisticsMmodeGrads> pfLogisticsMmodeGrads;
            BigDecimal pfjzPrice;
            pfLogisticsMmodeGrads = logisticsMmodeGrads.stream().filter(logisticsMmodeGrads1 -> weightCalPf.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && weightCalPf.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            pfjzPrice = (pfLogisticsMmodeGrads.size()!=0?pfLogisticsMmodeGrads.get(0).getKg():BigDecimal.ZERO);
            BigDecimal warehouseSurchargepf = (weightCalPf.multiply(fbaBox1.getWarehouseSurchargePrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
            fbaBox1.setWarehouseSurchargePf(warehouseSurchargepf);
            //实际抛发计重运费、费用说明：实际抛发计重运费=MAX（装箱抛重，单票起重）*抛发计重单价+仓库附加计重费用
            fbaBox1.setPriceTranCalWeightPredictPf(((weightCalPf.multiply(pfjzPrice)).add(warehouseSurchargepf)).setScale(2, BigDecimal.ROUND_HALF_UP));
            //实际抛发物流运费、费用说明：实际抛发物流运费=实际抛发计重运费+实际抛发材质附加费+实际抛发品名附加费+实际抛发清关费
            fbaBox1.setActualLogisticsFreightPf(fbaBox1.getPriceTranCalWeightPredictPf()
                    .add(fbaBox1.getPriceQualityExtraPredictPf())
                    .add(fbaBox1.getPriceProNameExtraPredictPf())
                    .add(fbaBox1.getPriceClearanceOpePf()));
        }
        fbaBox1.setUpdateTime(new Date());
        fbaBox1.setUpdateUser(ShiroUtils.getUserId());
        fbaBox1.setStatePrint("3");
        fbaBox1.setStatePrintName("配货清单和商品标和透明标已打印");
        fbaBox1.setState("2");
        fbaBox1.setStateName("已装箱");
        //新增详情数据
        fbaBoxDetailMapper.batchInsert(fbaBoxDetailListNew);
        //修改装箱详情
        fbaBoxMapper.updateByGuid(fbaBox1);
        return AjaxResult.success();
    }

    private BigDecimal precision(BigDecimal f){
        //根据数字未满5满5,未满10满10
        String s = f.stripTrailingZeros().toPlainString();
        String ff = f.toString();
        int rs = s.indexOf(".");
        if (rs != -1) {
            //取出第一位
            String first = s.substring(0,rs);
            //根据第一位小数5来判断，大于0.5以上进1,小于0.5的为0.5
            first = first + ".5";
            Double fD = Double.parseDouble(String.valueOf(f));
            Double firstD = Double.parseDouble(first);
            if (fD < firstD){
                ff = first;
            } else if(fD > firstD) {
                ff = String.valueOf(Math.round(fD));
            }
        }
        return new BigDecimal(ff);
    }
}
